// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#include <string>
#include <pollux/plan/reference_query_runner.h>
#include <pollux/parse/expressions.h>
#include <pollux/vector/type_aliases.h>

using namespace kumo::pollux::plan;

namespace kumo::pollux::test {
    /// Utility class that helps to run any expressions standalone. It takes input
    /// data, SQL, and dirty result vector if any from disk and run the expression
    /// described by SQL. It supports 3 modes:
    ///    - "verify": run expression and compare results between common and
    ///                simplified path
    ///    - "common": run expression only using common paths. (to be supported)
    ///    - "simplified": run expression only using simplified path. (to be
    ///                supported)
    class ExpressionRunner {
    public:
        /// @param inputPaths A comma separated list of paths to the on-disk vectors
        ///         that will be used as inputs to be fed to the expression.
        /// @param inputSelectivityVectorPath A comma separated list of paths to the
        ///        on-disk selectivity vectors that correspond 1-to-1 with the inputs
        ///        to be fed to the expression.
        /// @param sql Comma-separated SQL expressions.
        /// @param complexConstantsPath The path to on-disk vector that stores complex
        ///        subexpressions that aren't expressable in SQL (if any), used with
        ///        sql to construct the complete plan
        /// @param resultPath The path to the on-disk vector
        ///        that will be used as the result buffer to which the expression
        ///        evaluation results will be written.
        /// @param mode The expression evaluation mode, one of ["verify", "common",
        ///        "simplified"]
        /// @param numRows Maximum number of rows to process. 0 means 'all' rows.
        ///         Applies to "common" and "simplified" modes only.
        /// @param storeResultPath The path to a directory on disk where the results
        /// of expression or query evaluation will be stored. If empty, the results
        /// will not be stored.
        /// @param inputRowMetadataPath The path to on-disk serialized struct that
        ///        contains metadata about the input row vector like the columns
        ///        to wrap in lazy or dictionary encoding and the dictionary wrap.
        /// @param findMinimalSubExpression Whether to find minimum failing
        ///        subexpression on result mismatch.
        /// @param useSeperatePoolForInput Whether to use separate memory pools for
        ///        input vector and expression evaluation. This helps trigger
        ///        code-paths that can depend on vectors having different pools. For
        ///        eg, when copying a flat string vector copies of the strings stored
        ///        in the string buffers need to be created. If however, the pools
        ///        were the same between the vectors then the buffers can simply be
        ///        shared between them instead.
        ///
        /// User can refer to 'VectorSaver' class to see how to serialize/preserve
        /// vectors to disk.
        static void run(
            const std::string &inputPaths,
            const std::string &inputSelectivityVectorPath,
            const std::string &sql,
            const std::string &complexConstantsPath,
            const std::string &resultPath,
            const std::string &mode,
            vector_size_t numRows,
            const std::string &storeResultPath,
            const std::string &inputRowMetadataPath,
            std::shared_ptr<ReferenceQueryRunner> referenceQueryRunner,
            bool findMinimalSubExpression = false,
            bool useSeperatePoolForInput = true);

        /// Parse comma-separated SQL expressions. This should be treated as private
        /// except for tests.
        static std::vector<core::TypedExprPtr> parseSql(
            const std::string &sql,
            const TypePtr &inputType,
            memory::MemoryPool *pool,
            const VectorPtr &complexConstants);
    };
} // namespace kumo::pollux::test
